//
//  ETApiURLManager.m
//  PywSdk
//
//  Created by liangyidong on 16/1/18.
//  Copyright © 2016年 zero. All rights reserved.
//

#import "ETApiBaseManager.h"
#import "AIFApiProxy.h"
#import "ApiClient.h"
#import "PywMBProgressHUD+Pyw.h"

#define AXCallAPI(REQUEST_METHOD, REQUEST_ID)                                                       \
{                                                                                       \
REQUEST_ID = [[AIFApiProxy sharedApiProxy] callPOSTWithParams:apiParams seriviceIndentifier:self.child.seriviceType methodName:self.child.methodName success:^(AIFURLResponse *response){ \
[self successedOnCallingAPI:response];                                          \
} fail:^(AIFURLResponse *response) {                                                \
[self failedOnCallingAPI:response withErrorType:ETManagerErrorTypeDefault];  \
}];                                                                                 \
[self.requestIdList addObject:@(REQUEST_ID)];                                          \
}

@interface ETApiBaseManager()
@property (nonatomic, copy, readwrite) id fetchedRawData;
@property (nonatomic, copy, readwrite) NSString *errorMessage;
@property (nonatomic, readwrite) ETManagerErrorType errorType;
@property (nonatomic, strong) NSMutableArray *requestIdList;



@end

@implementation ETApiBaseManager


NSString *const UNIFYPARAMES_VER = @"ver";
NSString *const UNIFYPARAMES_NETWORKTYPE = @"networktype";
NSString *const UNIFYPARAMES_IMIE = @"imie";
NSString *const UNIFYPARAMES_OS = @"os";
NSString *const UNIFYPARAMES_IOSVER = @"ios_ver";
NSString *const UNIFYPARAMES_MODEL = @"model";
NSString *const UNIFYPARAMES_GAMEID = @"gameid";

NSString *const UNIFYPARAMES_SDK_TYPE = @"sdk_type";
NSString *const UNIFYPARAMES_Promo_Channel = @"promo_channel";
NSString *const UNIFYPARAMES_Promo_code = @"promo_code";

NSString *const UNIFYPARAMES_Bundle_Id = @"bundle_id";
NSString *const UNIFYPARAMES_Bundle_Ver = @"bundle_ver";
NSString *const UNIFYPARAMES_GAMEKEY = @"gamekey";

static NSString *promo_channel_pyw = @"21";
static NSString *promo_channel_fq = @"23";
static NSString *promo_channel_both = @"24";
+ (instancetype)manager{
    return [[[self class] alloc] init];
}

#pragma mark - getters and setters



// 请求列表
- (NSMutableArray *)requestList{
    if (!_requestIdList) {
        _requestIdList = [[NSMutableArray alloc] init];
    }
    return _requestIdList;
}

- (BOOL)isReachable{
    BOOL isReachability = [ApiClient sharedApiClient].isReachable;
    if (!isReachability) {
        self.errorType = ETManagerErrorTypeErrorTypeNoNetWork;
    }
    return isReachability;
}

- (BOOL)isLoading{
    return [self.requestList count] > 0;
}

#pragma mark - life cycle
- (instancetype)init{
    self = [super init];
    if (self) {
        _delegate = nil;
        _paramSource = nil;
        _fetchedRawData = nil;
        _errorMessage = nil;
        _errorType = ETManagerErrorTypeDefault;
        if ([self conformsToProtocol:@protocol(ETAPIManager)]) {
            self.child = (id<ETAPIManager>) self;
        }
    }
    return self;
}

#pragma mark - public methods
- (void)cancelAllRequests{
    [[AIFApiProxy sharedApiProxy] cancelRequestWithRequestIdList:self.requestIdList];
    [self.requestIdList removeAllObjects];
}

- (void)cancelRequestWithRequestId:(NSInteger)requestID{
    [self removeRequestIdWithRequestID:requestID];
    [[AIFApiProxy sharedApiProxy] cancelRequestWithRequestId:@(requestID)];
}

- (id)fetchDataWithReformer:(id<ETAPIManagerCallbackDataReformer>)reformer{
    id resultData = nil;
    if ([reformer respondsToSelector:@selector(manager:reformData:)]) {
        resultData = [reformer manager:self reformData:self.fetchedRawData];
    }else{
        resultData = [self.fetchedRawData mutableCopy];
    }
    return resultData;
}

#pragma mark - calling api
- (NSInteger)loadData{
    NSDictionary *params = [self.paramSource paramsForApi:self];
    params = [self unifiedParames:params];
    NSLog(@"request param:%@",params.description);
    NSInteger requestId = [self loadDataWithParams:params];
    return requestId;
}

- (NSInteger)loadDataWithParams:(NSDictionary *)params{
    NSInteger requestId = 0;
    NSDictionary *apiParams = [self reformParams:params];
    if ([self shouldCallAPIWithParams:apiParams]) {
        if ([self.validate manager:self isCorrectWithCallBackData:apiParams]) {
//            if ([self shouldCache] && [self hasCacheWithParams:apiParams]) {
//                return 0;
//            }
            if ([self isReachable]) {
                switch (self.child.requestType) {
                    case ETAPIManagerRequestTypeGet:
                        AXCallAPI(GET, requestId);
                        break;
                    case ETAPIManagerRequestTypePost:
                        AXCallAPI(POST, requestId);
                        break;
                    case ETAPIManagerRequestTypeRestGet:
                        AXCallAPI(RestfulGET, requestId);
                        break;
                    case ETAPIManagerRequestTypeRestPost:
                        AXCallAPI(RestfulPOST, requestId);
                        break;
                    default:
                        break;
                }
                NSMutableDictionary *params = [apiParams mutableCopy];
                params[kRTAPIBaseManagerRequestID] = @(requestId);
                [self afterCallingAPIWithParams:params];
                return requestId;
            }else{
                [self failedOnCallingAPI:nil withErrorType:ETManagerErrorTypeErrorTypeNoNetWork];
                return requestId;
            }
        }else{
            [self failedOnCallingAPI:nil withErrorType:ETManagerErrorTypeErrorTypeParamsError];
        }
    }
    return requestId;
}

#pragma mark - api callbacks
- (void)apiCallBack:(AIFURLResponse *)response{
    if (response.status == AIFURLResponseStatusSuccess) {
        [self successedOnCallingAPI:response];
    }else{
        [self failedOnCallingAPI:response withErrorType:ETManagerErrorTypeErrorTypeTimeout];
    }
}

- (void)successedOnCallingAPI:(AIFURLResponse *)response{
    if (response.content) {
        self.fetchedRawData = [response.content copy];
    }else{
        self.fetchedRawData = [response.responseData copy];
    }
    [self removeRequestIdWithRequestID:response.requestId];
    if ([self.validate manager:self isCorrectWithCallBackData:response.content]) {
        if ([self shouldCache] && !response.isCache) {
        }
        [self.delegate managerCallAPIDidSuccess:self];
    }
}

- (void)failedOnCallingAPI:(AIFURLResponse *)response withErrorType:(ETManagerErrorType)errorType
{
    self.errorType = errorType;
    [self removeRequestIdWithRequestID:response.requestId];
    [self.delegate managerCallApiDidFailed:self];
}

#pragma mark - method for interceptor
- (void)beforePerformSuccessWithResponse:(AIFURLResponse *)response{
    self.errorType = ETManagerErrorTypeErrorTypeSuccess;
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:beforePerformSuccessWithResponse:)]) {
        [self.interceptor manager:self beforePerformSuccessWithResponse:response];
    }
}

- (void)afterPerformSuccessWithResponse:(AIFURLResponse *)response{
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:afterPerformSuccessWithResponse:)]) {
        [self.interceptor manager:self afterPerformSuccessWithResponse:response];
    }
}

- (void)beforePerformFailWithResponse:(AIFURLResponse *)response{
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:beforePerformFailWithResponse:)]) {
        [self.interceptor manager:self beforePerformFailWithResponse:response];
    }
}

- (void)afterPerformFailWithResponse:(AIFURLResponse *)response{
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:afterPerformFailWithResponse:)]) {
        [self.interceptor manager:self afterPerformFailWithResponse:response];
    }
}

- (BOOL)shouldCallAPIWithParams:(NSDictionary *)params{
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:shouldCallAPIWithParams:)]) {
        return [self.interceptor manager:self shouldCallAPIWithParams:params];
    }else{
        return YES;
    }
}

- (void)afterCallingAPIWithParams:(NSDictionary *)params{
    if (self != self.interceptor && [self.interceptor respondsToSelector:@selector(manager:isCorrectWithParamsData:)]) {
        [self.interceptor manager:self shouldCallAPIWithParams:params];
    }
}

#pragma mark - method for child
- (void)cleanData{
    IMP childIMP = [self.child methodForSelector:@selector(cleanData)];
    IMP selfIMP = [self methodForSelector:@selector(cleanData)];
    
    if (childIMP == selfIMP) {
        self.fetchedRawData = nil;
        self.errorMessage = nil;
        self.errorType = ETManagerErrorTypeDefault;
    }else{
        if ([self.child respondsToSelector:@selector(cleanData)]) {
            [self.child cleanData];
        }
    }
}

- (NSDictionary *)reformParams:(NSDictionary *)params{
    IMP childIMP = [self.child methodForSelector:@selector(reformParams:)];
    IMP selfIMP = [self methodForSelector:@selector(reformParams:)];
    
    if (childIMP == selfIMP) {
        return params;
    }else{
        NSDictionary *result = nil;
        result = [self.child reformParams:params];
        if (result) {
            return  result;
        }else{
            return params;
        }
    }
}

- (BOOL)shouldCache{
    return YES;
}

#pragma mark - private methods
- (void)removeRequestIdWithRequestID:(NSInteger)requestId{
    NSNumber *requestIdToRemove = nil;
    for (NSNumber *storeRequestId in self.requestList) {
        if ([storeRequestId integerValue] == requestId) {
            requestIdToRemove = storeRequestId;
        }
    }
    if (requestIdToRemove) {
        [self.requestList removeObject:requestIdToRemove];
    }
}

- (BOOL)hasCacheWithParams:(NSDictionary *)params{
    NSString *serviceIdentifier = self.child.seriviceType;
    NSString *methodName = self.child.methodName;
    return YES;
}

- (NSDictionary *)unifiedParames:(NSDictionary *)parames{

    MutableDictionary *muParames = [[MutableDictionary alloc] init];
    [muParames setDictionary:parames];
    
    NSString *sdkVer = [PywAppInfo sharedAppInfo].verID;
    NSString *imie = [PywAppInfo sharedAppInfo].uuid;
    NSString *networkInfo = [[ApiClient sharedApiClient] networkInfo];
    NSString *model = [[PywAppInfo sharedAppInfo] model];
    NSString *sysVer = [PywAppInfo sharedAppInfo].sysVersion;
    NSString *gameId = [PywAppInfo sharedAppInfo].gameId;
    
    [muParames setObject:@([PywAppInfo sharedAppInfo].appType) forKey:UNIFYPARAMES_SDK_TYPE];   // Sdk类型
    NSString *promo_channel = @"";
    if([PywAppInfo sharedAppInfo].appType == AppTypePYW){
        promo_channel = promo_channel_pyw;
    }else if([PywAppInfo sharedAppInfo].appType == AppTypeFQ){
        promo_channel = promo_channel_fq;
    }else{
        promo_channel = promo_channel_both;
    }
    [muParames setObject:promo_channel forKey:UNIFYPARAMES_Promo_Channel];                      // 分包标识
    [muParames setObject:sdkVer forKey:UNIFYPARAMES_VER];               // sdk版本号
    [muParames setObject:networkInfo forKey:UNIFYPARAMES_NETWORKTYPE];  // 网络类型
    [muParames setObject:imie forKey:UNIFYPARAMES_IMIE];                // 手机IMEI
    [muParames setObject:@"IOS" forKey:UNIFYPARAMES_OS];                // 运行设备
    [muParames setObject:model forKey:UNIFYPARAMES_MODEL];              // 设备类型 iPhone
    [muParames setObject:sysVer forKey:UNIFYPARAMES_IOSVER];            // 设备系统版本 10.3
    [muParames setObject:gameId forKey:UNIFYPARAMES_GAMEID];            // GameId
    
    NSString *current_login_account = [PywPlatformMain sharedPlatformMain].account;
    if (current_login_account.length > 0) {
        [muParames setObject:current_login_account forKey:@"current_login_account"];  // 当前登录账号
    }

    if ([PywAppInfo sharedAppInfo].promo_code.length > 0) {
        [muParames setObject:[PywAppInfo sharedAppInfo].promo_code forKey:UNIFYPARAMES_Promo_code];           // 分包黑金卡标识
    }
    if ([PywAppInfo sharedAppInfo].promo_channel.length > 0) {
        [muParames setObject:[PywAppInfo sharedAppInfo].promo_channel forKey:UNIFYPARAMES_Promo_Channel];     // 分包渠道标识
    }
    [muParames setObject:[PywAppInfo sharedAppInfo].bundle_Id forKey:UNIFYPARAMES_Bundle_Id];   // bundle_id
    [muParames setObject:[PywAppInfo sharedAppInfo].bundle_ver forKey:UNIFYPARAMES_Bundle_Ver]; // 游戏版本
    [muParames setObject:[PywAppInfo sharedAppInfo].gameKey forKey:UNIFYPARAMES_GAMEKEY];       // 游戏Gamekey
    
    return [muParames copy];
}

@end
